﻿using System;
using NUnit.Framework;
using ValidationFramework.Reflection;

namespace ValidationFramework.Tests
{
	[TestFixture]
	[Ignore]
	public class PerformanceTest
	{
		public class ClassToValidate
		{

			[RequiredIntRule]
			public int PropertyToValidate
			{
				get;
				set;
			}

			public int TestMethod([RequiredIntRule] int param1)
			{
				return 0;
			}
		}


		readonly RuntimeTypeHandle classToValidateHadle = typeof(ClassToValidate).TypeHandle;
		readonly RuntimeMethodHandle methodToValidateHadle = typeof(ClassToValidate).GetMethod("TestMethod").MethodHandle;


		[Test]
		public void TypeCacheGetType()
		{
			const int iterations = 100000;
			TypeCache.Clear();
			TypeCache.GetType(classToValidateHadle);
			TypeCache.Clear();
			using (var disposableStopwatch = new DisposableStopwatch("TypeCache.GetType constructor", iterations))
			{
				disposableStopwatch.Run(delegate
				{
					TypeCache.GetType(classToValidateHadle);
					TypeCache.Clear();
				});
			}
		}

		[Test]
		public void MethodCacheGetMethod()
		{
			const int iterations = 100000;
			MethodCache.Clear();
			MethodCache.GetMethod(methodToValidateHadle);
			MethodCache.Clear();
			using (var disposableStopwatch = new DisposableStopwatch("MethodCacheGetMethod", iterations))
			{
				disposableStopwatch.Run(delegate
				{
					MethodCache.GetMethod(methodToValidateHadle);
					MethodCache.Clear();
				});
			}
		}
		[Test]
		public void MethodCacheGetMethodUsingDelegate()
		{
			var classToValidate = new ClassToValidate();
			const int iterations = 100000;
			MethodCache.Clear();
			MethodCache.GetMethod(new Func<int, int>(classToValidate.TestMethod));
			MethodCache.Clear();
			using (var disposableStopwatch = new DisposableStopwatch("MethodCacheGetMethod", iterations))
			{
				disposableStopwatch.Run(delegate
				{
					MethodCache.GetMethod(new Func<int, int>(classToValidate.TestMethod));
					MethodCache.Clear();
				});
			}
		}


		[Test]
		public void PropertyValidationManagerConstructor()
		{
			const int iterations = 1000000;
			TypeCache.Clear();
			TypeCache.GetType(classToValidateHadle);
			TypeCache.Clear();
			var classToValidate = new ClassToValidate();
			using (var disposableStopwatch = new DisposableStopwatch("PropertyValidationManager constructor", iterations))
			{
				disposableStopwatch.Run(delegate
											{
												new PropertyValidationManager(classToValidate);
												TypeCache.Clear();
											});
			}
        }

#if (!WindowsCE)
        [Test]
		public void ValidateValidPropertyUsingString()
		{
			const int iterations = 1000000;
			TypeCache.Clear();
			const string memberName = "PropertyToValidate";
			var classToValidate = new ClassToValidate {PropertyToValidate = 10};
		    var propertyValidationManager = new PropertyValidationManager(classToValidate);
			using (var disposableStopwatch = new DisposableStopwatch("Validate Valid Property using string", iterations))
			{
				disposableStopwatch.Run(() => propertyValidationManager.Validate(memberName));
			}
		}

		[Test]
		public void ValidateInvalidPropertyUsingString()
		{
			const int iterations = 1000000;
			TypeCache.Clear();
			const string memberName = "PropertyToValidate";
			var classToValidate = new ClassToValidate();
			var propertyValidationManager = new PropertyValidationManager(classToValidate);
			using (var disposableStopwatch = new DisposableStopwatch("Validate Invalid Property using string", iterations))
			{
				disposableStopwatch.Run(() => propertyValidationManager.Validate(memberName));
			}
		}
		[Test]
		public void ValidateInvalidPropertyUsingLambda()
		{
			const int iterations = 1000000;
			TypeCache.Clear();
			var classToValidate = new ClassToValidate();
			var propertyValidationManager = new PropertyValidationManager(classToValidate);
			using (var disposableStopwatch = new DisposableStopwatch("Validate invalid Property using Lambda", iterations))
			{
				disposableStopwatch.Run(() => propertyValidationManager.Validate(() => classToValidate.PropertyToValidate));
			}
		}

		[Test]
		public void ValidateValidPropertyUsingLambda()
		{
			const int iterations = 1000000;
			TypeCache.Clear();
			var classToValidate = new ClassToValidate {PropertyToValidate = 10};
		    var propertyValidationManager = new PropertyValidationManager(classToValidate);
			using (var disposableStopwatch = new DisposableStopwatch("Validate Valid Property using Lambda", iterations))
			{
				disposableStopwatch.Run(() => propertyValidationManager.Validate(() => classToValidate.PropertyToValidate));
			}
		}
#endif
	}
}
